package websocket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.HTMLFilter;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lixuwei
 */
@ServerEndpoint("/websocket/chat")
public class ChatAnnotation {
    
    public static final Logger Log = LoggerFactory.getLogger(ChatAnnotation.class);

    public static final String GUEST_PREFIX = "Guest";
    public static final AtomicInteger connectionIds = new AtomicInteger(0);
    public static final Set<ChatAnnotation> connections = new CopyOnWriteArraySet<ChatAnnotation>();
    
    private final String nickname;
    private Session session;
    
    public ChatAnnotation(){
        nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
    }
    
    @OnOpen
    public void start(Session session){
        this.session = session;
        connections.add(this);
        String message = String.format("* %s %s", nickname, "has joined");
        Log.debug(message);
        broadcast(message);
    }
    
    @OnClose
    public void end(){
        connections.remove(this);
        String message = String.format("* %s %s", nickname, "has disconnected.");

        broadcast(message);
    }
    
    @OnMessage
    public void incoming(String message) {
        //never trust the client
        String filteredMessage = String.format("%s : %s", nickname, HTMLFilter.filter(message.toString()));
        Log.debug("broadcast : " + filteredMessage);
        broadcast(filteredMessage);
    }
    
    @OnError
    public void onError(Throwable t) throws Throwable{
       Log.error("Chat Error: " + t.toString(),t);
    }
    

    /**
     * 广播消息 
     * @param msg
     */
    private static void broadcast(String msg){
        for(ChatAnnotation client : connections){
            try {
                synchronized (client){
                    client.session.getBasicRemote().sendText(msg);
                }
            } catch (IOException e) {
                Log.debug("Chat Error: Failed to send message to client",e);
                connections.remove(client);
                try {
                    client.session.close();
                } catch (IOException e1) {
                    //Ignore
                }

                String message = String.format("* %s %s", client.nickname, "has been disconnected.");
                broadcast(message);
            }
        }
    }
    
    
}
